package com.spring.campus_express_delivery.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.campus_express_delivery.entity.PageBean;
import com.spring.campus_express_delivery.entity.Users;
import com.spring.campus_express_delivery.interceptor.RequiredPermission;
import com.spring.campus_express_delivery.service.UsersService;
import com.spring.campus_express_delivery.util.JwtToken;
import com.spring.campus_express_delivery.util.MyUtil;
import com.spring.campus_express_delivery.util.RedisUtil;
import com.spring.campus_express_delivery.util.ResponseEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.apache.catalina.User;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.Map;
import java.util.UUID;

@CrossOrigin
@Controller
@RequestMapping("/users")
@Api(value = "UsersController", description = "用户相关api")
public class UsersController {
    Boolean flag;
    MyUtil myUtil=new MyUtil();
    //MyUtil myUtil=new MyUtil();
    @Autowired
    private UsersService usersService;
    @Autowired
    private RedisUtil redisUtil;
        /**
         * 微信小程序注册用户接口
         * @param model
         * @param code //用户登录凭证
         * @param rawData  //原始数据
         * @return
         */
        @ApiOperation("小程序注册用户")
        @ResponseBody
        @PostMapping("/wx/register")
        public ResponseEntity doRegister(Model model,
                                         @RequestParam(value = "code",required = false) String code,
                                         @RequestParam(value = "rawData",required = false) String rawData){

            ResponseEntity responseData;
            JSONObject rawDataJson = JSON.parseObject( rawData );
            JSONObject SessionKeyOpenId = myUtil.getcode( code );
            String appid = SessionKeyOpenId.getString("openid" );
            String sessionKey = SessionKeyOpenId.getString( "session_key" );

            //通过openid来查询此用户是否存在
            Users user = usersService.selectUserByOpenid( appid );
            System.out.println("当前user为：" + user+"可以插入用户");
            //生成id
            String uid = myUtil.getStringID();
            if(user==null){//但是你下面换了 好像你插入进去你这个user并没有用到，那我换一下试试，但我感觉不是这个问题；我想到的是要么前端返回的参数不对，所以插入的appid没有，要不就是后端代码写不对，插不进去appid；
                responseData = ResponseEntity.ok();
                //入库
                int authority = 2;
                String whether_delete="否";
                String nickName = rawDataJson.getString( "nickName" );
                String avatar = rawDataJson.getString( "avatarUrl" );
                String country = rawDataJson.getString("country");
                String province = rawDataJson.getString("province");
                String city = rawDataJson.getString("city");
                String address = country + province + city;

                user = new Users();
                user.setAuthority(authority);//你注册的时候能插入数据库是把，可以插入，就是没有appid、state
                user.setUsername(nickName);
                user.setAddress(address);
                user.setRemark(nickName);
                user.setWhether_delete(whether_delete);
                user.setScope( sessionKey );
                user.setAppid( appid );
                user.setHead_portrait( avatar );
                user.setState( nickName );
                user.setCreate_time(myUtil.getTime());
                user.setIdentity_id(appid);
                user.setPassword(appid);
                usersService.insertWXUser( user );
                responseData.putDataValue("appid",user.getAppid());
                responseData.putDataValue("msg","注册成功");
                responseData.putDataValue("timestamp",myUtil.getTime());
                System.out.println("插入数据库成功");
                return responseData;
            }else {
                //已存在
                responseData = ResponseEntity.badRequest();
                responseData.putDataValue("msg","用户已存在");
                responseData.putDataValue("timestamp",myUtil.getTime());
                System.out.println("用户openid已存在,不需要插入");
            }
            return responseData;
        }

        /**
         * 微信小程序登陆接口
         * @param model
         * @param code //用户登录凭证
         * @param rawData  //原始数据
         * @return
         * @throws UnsupportedEncodingException
         * @throws JsonProcessingException
         */
        @ApiOperation("微信小程序登录")
        @ResponseBody
        @PostMapping("/wx/login")
        public ResponseEntity doLogin(Model model,
                                      @RequestParam(value = "code",required = false) String code,
                                      @RequestParam(value = "rawData",required = false) String rawData) throws UnsupportedEncodingException, JsonProcessingException {
            ResponseEntity responseEntity;
            JSONObject SessionKeyOpenId = myUtil.getcode( code );
            String appid = SessionKeyOpenId.getString("openid" );
            //JSONObject rawDataJson = JSON.parseObject( rawData );
            String sessionKey = SessionKeyOpenId.getString( "session_key" );
            //通过openid来查询此用户是否存在
            Users user = usersService.selectUserByOpenid( appid );
            if(user == null){
                responseEntity = ResponseEntity.badRequest();
                responseEntity.putDataValue("msg", "用户不存在请先授权登录");
                responseEntity.putDataValue("timestamp",myUtil.getTime());
                return responseEntity;
            }else {
                responseEntity = ResponseEntity.ok();
                //给用户jwt加密生成token
                String token = JwtToken.sign(user, 30L * 60L * 1000L);
                responseEntity.putDataValue("appid", user.getAppid());
                responseEntity.putDataValue("token", token);
                responseEntity.putDataValue("timestamp",myUtil.getTime());
                responseEntity.putDataValue("id",user.getId());
                responseEntity.putDataValue("msg","登录成功");
            }
            return responseEntity;
        }
    /**
     * 微信获取用户信息接口
     * @param Authorization
     * @param //response
     * @return responseEntity
     * @throws IOException
     */
    @ApiOperation("微信小程序获取用户信息")
    @PostMapping("/wx/getInfo")
    @ResponseBody
    public ResponseEntity getWxInfo(@RequestHeader String Authorization
                                    /*HttpServletResponse response*/) throws IOException {
        ResponseEntity responseEntity;
        String token = Authorization;
            responseEntity = ResponseEntity.ok();
            Users user = JwtToken.unsign(token, Users.class);
            //解密token后的identity_id与用户传来的identity_id不一致，大多是因为token过期
                responseEntity.putDataValue("users", user);
                return responseEntity;

    }


    /**
     * web端注册用户
     * @param identity_id
     * @param password
     * @param authority
     * @return
     * @throws IOException
     * @throws TokenExpiredException
     */
    @ApiOperation("web端注册用户")
    @PostMapping("/web/register")
    @ResponseBody
    public ResponseEntity register( @RequestParam(required = true) String identity_id,
                                    @RequestParam(required = true) String password,
                                   @RequestParam(required = true) int authority,
                                   @RequestHeader String Authorization) throws IOException, TokenExpiredException {
        ResponseEntity responseEntity;
        String token = Authorization;
        //判断token是否存在或过期
        if (flag = myUtil.judgeToken(token)){
            responseEntity = ResponseEntity.forbidden();
            responseEntity.putDataValue("msg","token不存在或已过期");
            return responseEntity;
        }
        Users users = JwtToken.unsign(token, Users.class);
        //只有超级管理员才可以注册用户，authority为0是超级管理员，1是管理员，2是普通用户
        if (users.getAuthority()!=0){
            responseEntity = ResponseEntity.unauthorized();
            responseEntity.putDataValue("msg","权限错误");
            responseEntity.putDataValue("timestamp",myUtil.getTime());
            return responseEntity;
        }
        //根据identity_id查询数据库是否有该用户存在，不存在则注册，存在则注册失败
        Users userFromBase = usersService.selectUserByIdentityId(identity_id);
        if (userFromBase == null){
            responseEntity = ResponseEntity.ok();
            Users user = new Users();
            user.setIdentity_id(identity_id);
            user.setPassword(password);
            if (authority < 0 || authority >= 2) {
                responseEntity = ResponseEntity.forbidden();
                responseEntity.putDataValue("msg", "权限输入不合理，注册失败");
                return responseEntity;
            }
            user.setAuthority(authority);
            String whether_delete="否";
            user.setWhether_delete(whether_delete);
            user.setCreate_time(myUtil.getTime());
            usersService.insertWebUser(user);
            responseEntity.putDataValue("id",user.getId());
            responseEntity.putDataValue("msg","注册成功");
        }else {
            responseEntity = ResponseEntity.badRequest();
            responseEntity.putDataValue("msg","注册失败");
        }

        return responseEntity;
    }

    /**
     * web登录接口
     * @param identity_id
     * @param password
     */
    @ApiOperation("web端登录")
    @PostMapping("/web/login")
    @ResponseBody
    public ResponseEntity login(@RequestParam(required = true) String identity_id, @RequestParam(required = true) String password) throws IOException {
        ResponseEntity responseEntity = ResponseEntity.ok();
        Users userFromBase = usersService.selectUserByIdentityId(identity_id);
        if(userFromBase==null){
            responseEntity =  ResponseEntity.customerError();
            responseEntity.putDataValue("msg","用户不存在");
            return responseEntity;
        }
            if(userFromBase.getIdentity_id().equals(identity_id) &&
                    userFromBase.getPassword().equals(password)) {
                //给用户jwt加密生成token
                String token = JwtToken.sign(userFromBase, 60L * 1000L * 30L);//sign()方法是static修饰的，所以直接用类名调用，不需要创建对象
                //封装成对象返回给客户端
                responseEntity.putDataValue("id",userFromBase.getId());
                responseEntity.putDataValue("identity_id", userFromBase.getIdentity_id());//调用ResponseEntity类的putDataValue方法将userID和token放进map中然后返回
                responseEntity.putDataValue("token", token);
                responseEntity.putDataValue("authority",userFromBase.getAuthority());
                responseEntity.putDataValue("head_portrait",userFromBase.getHead_portrait());
                responseEntity.putDataValue("username",userFromBase.getUsername());
            /* BS架构中,客户端与服务器一连接在服务端就会自动创建一来个session对象.session.setAttribute("username",username);
这句话的意思就是自说,当客户端执行了某个操作后(刚一登陆,或其他操作)服务百端就会在session对象中存储一个名称为username的参数这个相当于hashMap,
"username" 相当于key username就是key对应的值(但注意这个值度必须是一个对象知).这样以后你可以通过session.getAttribute("username")的方法获得这个对象.
比如说,当用户道已登录系统后你就在session中存储了一个用户信息对象,此后你可以随时从session中将这个对象取出来进行一些操作,比如进行身份验证等等.
             */

            }
            else{
                responseEntity =  ResponseEntity.customerError();
                responseEntity.putDataValue("msg","账号密码错误");
            }
        return responseEntity;
    }
    /**
     * 获取当前登录用户信息
     * @return
     * @throws Exception
     */
    @ApiOperation("web端获取当前登录用户信息")
    @PostMapping("/web/getinfo")
    @ResponseBody
    public ResponseEntity preHandle(@RequestHeader String Authorization) throws Exception {

        String token = Authorization;
        ResponseEntity responseData;
            responseData = ResponseEntity.ok();
            Users user = JwtToken.unsign(token, Users.class);
            //解密token后的userId与用户传来的userId不一致，大多是因为token过期
                responseData.putDataValue("users", user);
                return responseData;

    }


    /**
     * 修改自己信息接口
     * @param username
     * @param phone
     * @param address
     * @param remark
     * @param password
     * @return
     * @throws IOException
     */
    @ApiOperation("修改自己信息")
    @PostMapping("/web/update_info")
    @ResponseBody
    public ResponseEntity updateUserInfoByMyself(@RequestParam(required = false) String username,
                                                 @RequestParam(required = false) String phone,
                                                 @RequestParam(required = false) String address,
                                                 @RequestParam(required = false) String remark,
                                                 @RequestParam(required = false) String password,
                                                 @RequestParam(required = false) String identity_id,
                                                 @RequestHeader String Authorization,
                                                 @RequestParam(required = true) MultipartFile pictureFile) throws IOException, ParseException {

        ResponseEntity responseData;
        String token = Authorization;
        //通过token解密出来的user对象
        Users user = JwtToken.unsign(token, Users.class);
        String head_portrait = MyUtil.testPrint(pictureFile);
        if (user.getIdentity_id() == identity_id) {
            responseData = ResponseEntity.forbidden();
            responseData.putDataValue("msg", "用户学号相同，修改失败");
            return responseData;
        }
        user.setUsername(username);
        user.setPhone(phone);
        user.setAddress(address);
        user.setRemark(remark);
        user.setPassword(password);
        user.setHead_portrait(head_portrait);
        user.setIdentity_id(identity_id);
        user.setUpdate_time(myUtil.getTime());
        //修改信息
        usersService.updateInfoByMyself(user);
        responseData = ResponseEntity.ok();
        responseData.putDataValue("msg","修改数据成功");
        //删除缓存
        String key = "users_" + user.getId();
        if (redisUtil.hasKey(key)) {
            redisUtil.del(key);
        }
        System.out.println("修改数据成功");
        return responseData;
    }
    /**
     * 用户列表接口
     * @param size
     * @param page
     * @param sort
     * @param asc
     * @param Authorization
     * @return
     * @throws IOException
     */
    @ApiOperation("用户列表")
    @PostMapping("/web/users_list")
    @ResponseBody
    @RequiredPermission(0)//只有超级管理员才可以
    public ResponseEntity selectUsers(@RequestParam(value = "size",required = false,defaultValue = "10") int size,
                                     @RequestParam(value = "page",required = false,defaultValue = "1") int page,
                                     @RequestParam(value = "sort",required = false,defaultValue = "id") String sort,
                                     @RequestParam(value = "asc",required = false,defaultValue = "asc") String asc,
                                     @RequestHeader String Authorization) throws IOException {
        ResponseEntity responseData;
        String token = Authorization;
        //通过token解密出来的user对象
        Users user = JwtToken.unsign(token, Users.class);
        PageBean<Users> pagemsg = usersService.selectUsersByPage(size, page, sort, asc);
        responseData = ResponseEntity.ok();
        responseData.putDataValue("records",pagemsg);
        return responseData;
    }
    /**
     * 根据identity_id查询用户信息
     *
     * @param identity_id
     * @return
     * @throws Exception
     */
    @ApiOperation("根据identity_id查询用户信息")
    @GetMapping("/web/selectUserByIdentityId")
    @ResponseBody
    @RequiredPermission(0)
    public ResponseEntity selectUserByIdentityId(@RequestParam(value = "identity_id",required = true) String identity_id, @RequestHeader String Authorization)
            throws Exception {
        ResponseEntity responseData;
        String token = Authorization;
        responseData = ResponseEntity.ok();
        Users userFromBase = usersService.selectUserByIdentityId(identity_id);
        responseData.putDataValue("users", userFromBase);
        return responseData;

    }
    /**
     * 删除用户
     *
     * @param id
     * @return
     * @throws IOException
     */
    @ApiOperation("删除用户")
    @GetMapping("/web/delete")
    @ResponseBody
    @RequiredPermission(0)
    public ResponseEntity deleteUser(@RequestParam(required = true) Integer id, @RequestHeader String Authorization) throws IOException {
        ResponseEntity responseData;
        String token = Authorization;
        usersService.deleteUserById(id);
        responseData = ResponseEntity.ok();
        responseData.putDataValue("msg", "删除数据成功");
        //删除缓存
        String key = "users_" + id;
        if (redisUtil.hasKey(key)){
            redisUtil.del(key);
        }
        return responseData;
    }
    /**
     * 统计用户数量
     */
    @ApiOperation("统计用户数量")
    @GetMapping("/web/count")
    @ResponseBody
    public ResponseEntity count() throws IOException {
        ResponseEntity responseData;
        Map<String, Integer> count = usersService.count();
        responseData = ResponseEntity.ok();
        responseData.putDataValue("count", count);
        return responseData;
    }

    /**
     * 根据id修改用户信息接口
     * @param id
     * @param password
     * @param identity_id
     * @param authority
     * @param Authorization
     * @return
     * @throws IOException
     * @throws ParseException
     */
    @ApiOperation("根据id修改用户信息")
    @PostMapping("/web/update_info_id")
    @ResponseBody
    public ResponseEntity updateUsersInfoById(
            @RequestParam(required = true) Integer id,
            @RequestParam(required = false) String password,
            @RequestParam(required = false) String identity_id,
            @RequestParam(required = false) Integer authority,
            @RequestHeader String Authorization) throws IOException, ParseException {
        ResponseEntity responseData;
        String token = Authorization;

        //通过查询id来判断此用户是否存在
        Users user = usersService.selectUsersById(id);
        if (user == null){
            responseData = ResponseEntity.badRequest();
            responseData.putDataValue("msg","没有该用户");
        }else {
            if (user.getIdentity_id() == identity_id) {
                responseData = ResponseEntity.forbidden();
                responseData.putDataValue("msg", "用户学号已存在，修改失败");
                return responseData;
            }
            responseData = ResponseEntity.ok();
            user.setPassword(password);
            user.setIdentity_id(identity_id);
            user.setAuthority(authority);
            user.setUpdate_time(myUtil.getTime());
            //修改信息
            usersService.updateUsersInfoById(user);
            responseData.putDataValue("msg","修改成功");
            //删除缓存
            String key = "users_" + id;
            if (redisUtil.hasKey(key)){
                redisUtil.del(key);
            }
        }
        return responseData;
    }
    /**
     * 导入用户信息
     * @param userFiles
     * @Header Authorization
     * @thorws IOException
     */
    @ApiOperation("导入用户信息api")
    @PostMapping("web/importUsersExcel")
    @ResponseBody
    @RequiredPermission(0)
    public ResponseEntity importUsersExcel(@RequestParam MultipartFile userFiles,@RequestHeader String Authorization) throws IOException{
        String token = Authorization;
        usersService.importUsersExcel(userFiles);
        ResponseEntity responseEntity;
        responseEntity=ResponseEntity.ok();
        responseEntity.putDataValue("msg","导入用户信息成功");
        return responseEntity;//那个是impl文件
    }

    /**
     * poi将数据库中的用户数据批量导出到Excel
     * @param response
     * @Header Authorization
     * @throws Exception
     */
    @ApiOperation("导出用户信息api")
    @PostMapping("web/exportUsersExcel")
    @ResponseBody
    @RequiredPermission(0)
    public void exportUsersExcel(HttpServletResponse response,@RequestHeader String Authorization)throws Exception {
        String token = Authorization;
        usersService.exportUsersExcel(response);
    }
    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    @ApiOperation("根据id查询用户")
    @GetMapping("/web/select_user_id")
    @ResponseBody
    public ResponseEntity selectId(@RequestParam(required = true) int id) {
        ResponseEntity responseEntity;
        responseEntity = ResponseEntity.ok();
        //查询缓存
        String key="users_"+id;
        boolean b = redisUtil.hasKey(key);
       //如果redis中存在 查询缓存
        if (b){
            Users user = (Users)redisUtil.get(key);
            responseEntity=ResponseEntity.ok();
            responseEntity.putDataValue("users",user);
            return responseEntity;
        }
        Users users = usersService.selectId(id);
        responseEntity.putDataValue("users",users);
        //设置缓存
        redisUtil.set("users_"+id,users);
        return responseEntity;
    }
}
